<!--
 * @Author: 黄宇/Hyuishine
 * @Date: 2022-09-29 09:39:50
 * @LastEditors: 黄宇/Hyuishine
 * @LastEditTime: 2023-10-24 19:33:21
 * @Description: 1、进入人脸识别 页面，来一个按钮：开始活体检测。
                 2、提示眨眨眼 拍一张，中间 拍两张， 即第 1秒 第2秒。第3秒不拍。
                 3、然后进入到张张嘴页面，开始拍一张，中间拍两张 第1秒 第2秒 第3秒不拍，总共6张。 
                临时路径 存储到一个数组，全部拍完 提示  正在验证，请稍后。然后遍历图片数组，传到后端校验。校验不通过 就重试
 * @Email: hyuishine@gmail.com
 * @Company: 3xData
 * @youWant: add you want
-->
<template>
  <view :style="{ height: windowHeight + 'px' }">

    <!-- 提示 跟 遮罩层 -->
    <view class="camera_tip" :style="{ color: detectSteps[curDetectStep].color || 'red' }">
      {{ detectSteps[curDetectStep].tip }}
    </view>
    <view class="camera_coverLayer"></view>
    <video id="video" :controls="false" :show-center-play-btn="false" :enable-progress-gesture="false"
      :muted="true" style="
        width: 375px;
        height: 667px;
      "></video>
    <view class="bottom font-36-fff" :style="paddingBottom">
      <view class="wrap">
        <view @click="btn_startDetect()" v-if="curDetectStep === 0">
          开始检测
        </view>
      </view>
    </view>
  </view>
</template>

<script>
import { baseApiUrl, baseImgUrl } from '@/config.js';
import { mapMutations } from 'vuex';
export default {
  data() {
    return {
      flip: false, // 摄像头false 为前置
      baseImgUrl: baseImgUrl,
      cameraContext: {}, // 相机实例
      windowHeight: '',
      cameraHeight: '',

      faceImages: [], // 采集的人脸照片，共六张
      curDetectStep: 0, // 当前所属步骤
      detectSteps: [ // 检测步骤，以及相关提示
        { mark: '准备', tip: '请正对屏幕，点击下方“ 开始检测 ”' },
        { mark: '眨眼', tip: '请眨眨眼', color: 'red' },
        { mark: '张嘴', tip: '请张张嘴', color: 'green' },
        { mark: '结束', tip: '正在识别，请稍后' }
      ],
      label: null,

      // 画布实例
      canvas: null,
      // 视频实例
      video: null,
      width: 375,
      height: 667,
    }
  },

  onLoad(options) {
    this.label = options.label

    this.width = window.innerWidth || 375;
    this.height = window.innerHeight || 667;
    this.init();
  },

  methods: {
    ...mapMutations(['unitTask', 'save_examine']),
    async init() {
      let videoStream = await navigator.mediaDevices.getUserMedia({
        video: {
          width: this.height,
          height: this.width,
          facingMode: "user" // 前置摄像头，或使用 "environment" 表示后置摄像头
        },
        audio: false,
      });
      this.video = document.getElementsByTagName("video")[0];
      //挂在视频流
      this.$set(this.video, 'srcObject', videoStream)
      //设置播放
      //PS：手机端只有设置静音该方法调用才有效
      this.video.play();

      // 创建canvas
      const canvas = document.createElement("canvas");
      canvas.width = this.width;
      canvas.height = this.height;
      canvas.style.display = 'none'
      document.body.appendChild(canvas);
      this.canvas = canvas;
    },
    btn_startDetect() {
      this.curDetectStep++
      this.takePhoto() // 第一张, 开始眨眼的

      // 眨眼 第二张
      let timer_winkTwo = setTimeout(() => {
        this.takePhoto()
        clearTimeout(timer_winkTwo)
      }, 1000)

      // 眨眼 第三张
      let timer_winkThree = setTimeout(() => {
        this.takePhoto()
        clearTimeout(timer_winkThree)
      }, 2000)


      // 张嘴 第一张
      let timer_gapeOne = setTimeout(() => {
        this.curDetectStep++
        this.takePhoto()
        clearTimeout(timer_gapeOne)
      }, 3000)

      // 张嘴 第二张
      let timer_gapeTwo = setTimeout(() => {
        this.takePhoto()
        clearTimeout(timer_gapeTwo)
      }, 4000)

      // 张嘴 第三张
      let timer_gapeThree = setTimeout(() => {
        this.takePhoto()
        clearTimeout(timer_gapeThree)
      }, 5000)

      // 结束
      let timer_update = setTimeout(() => {
        this.curDetectStep++
        this.uploadImage()
        clearTimeout(timer_update)
      }, 6000)
    },


    // 拍照
    async takePhoto() {
      try {
        const ctx = this.canvas.getContext("2d");
        ctx.drawImage(this.video, 0, 0, this.width, this.height); // 必须调用draw方法来渲染canvas上的内容
        const base64Image = this.canvas.toDataURL("image/png"); // 获取 base64 编码的图片
        this.faceImages.push(base64Image);
        ctx.clearRect(0, 0, this.width, this.height);
      } catch (e) {
        console.log(e);
      }
    },

    // 上传图片
    uploadImage() {
      var uploadSuccess = [] // 文件上传的异步

      this.faceImages.forEach(url => {

        uploadSuccess.push(
          new Promise((resolve, reject) => {
            // 上传图片，文件列表上传 小程序不支持
            uni.uploadFile({
              url: baseApiUrl + "/common/temporaryUpload",
              name: "file",
              header: {
                Authorization: this.$store.state.login.userInfo.token,
              },
              filePath: url,
              success: uploadFileRes => {
                this.result = true
                resolve(JSON.parse(uploadFileRes.data).fileName)
              },
              fail: err => {
                reject(err)
              }
            })
          })
        )
      })

      Promise.all(uploadSuccess).then(urls => {
        // this.$store.state.unitTask[this.label] = urls.join(',')
        this.save_examine({ key: this.label, value: urls.join(',') })
        this.btn_back()

      }).catch(err => {
        console.log('人脸识别报错：', err)
        // todo 至少有一张上传失败
        this.curDetectStep = 0
        uni.showToast({
          title: '识别失败，请重试',
          icon: "none",
          mask: false,
          duration: 3000
        })
      })
    },

    //返回
    btn_back() {
      uni.navigateBack()
    }
  },
  computed: {
    // 底部导航栏高度 单位px
    navigationBarHeight() {
      return uni.getStorageSync("menuInfo").navigationBarHeight || uni.getStorageSync("menuInfo").statusBarHeight / 2;
    },
    // 底部菜单padding掉导航栏的位置
    paddingBottom() {
      if (this.navigationBarHeight) {
        return "padding-bottom:" + this.navigationBarHeight + "px;";
      }
      else {
        return "";
      }
    }
  }
}
</script>

<style lang="less" scoped>
.camera_coverLayer {
  background-size: 100% 100%;
  background-position: 50% 50%;
  background-repeat: no-repeat;
  width: 100vh;
  height: 100vh;
  position: absolute;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
  z-index: 2;
  background-image: url("/static/camera_coverLayer.png");
}

.controls {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

.bottom {
  width: 100%;
  background-color: #000;
  z-index: 4;
  position: absolute;
  bottom: 0;


  .wrap {
    padding: 0 80rpx;
    height: 160rpx;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}

.font-36-fff {
  font-size: 36rpx;
  color: #fff;
}

.menu-flip {
  width: 100rpx;
}

.camera_tip {
  position: absolute;
  z-index: 3;
  top: 15%;
  font-size: 36rpx;
  word-break: break-all;
  margin: 0 12px;
  width: calc(100vw - 72rpx);
  color: red;
  text-align: center;
  white-space: break-spaces;
}
</style>
